        TITL DAI FIRMWARE 1E7D2-1EA0D  V1.0  Rev.1
        ORG   :E7D2
*
*
*
*******
* SIN *
*******
*
* MACC = SIN (MACC)  (Angle expressed in radians).
*
* See XCOS for explanation.
*
XSIN    PUSH  PSW
        PUSH  B
        PUSH  D
        PUSH  H
        JMP   :E7E3     To common part XSIN/XCOS
*
*******
* COS *
*******
*
* MACC = COS (MACC)  (Angle expressed in radians).
*
* Method: Polynomial approximation.
*
* Cos(X) is converted: cos(X) = sin(X+PI/2).
*
* Given X, N and Y are defined for:
*      X/(2*PI) = N + Y; N is integer part.
*
* All arguments are converted to a range -PI/2 to
* +PI/2:
*      sin(N*2*PI+K) = sin(K)
*      sin(PI/2+K)   = sin(PI/2-K)
*      sin(PI*3/2+K) = sin(PI*3/2-K)
*      sin(-PI/2+K)  = sin(-PI/2-K).
*
* Polynomial approx. F(Y) for sin(2*PI*Y) is:
*      F(Y) = a1*Y + a2*Y^3 + ... + a5*Y^9.
*
XCOS    PUSH  PSW
        PUSH  B
        PUSH  D
        PUSH  H
        LXI   H,:E833   Addr PI/2
        CALL  :EA72     X = X + PI/2
 REM
* Entry from XSIN:
 REM
L1E132  LXI   H,:E83F   Addr PI*2
        CALL  :EA20     MACC = X/(2*PI) = N+Y
        CALL  :E154     Get FRAC(MACC) = Y
        LXI   H,:00D5   Addr MACC
        MOV   A,M       Get exp.byte
        ANI   :7F       Exp only
        JZ    :E7FA     Jump if exp is 0
        CPI   :7E
        JC    :E818     Jump if exp < 7E
L1E133  CMP   M         Comp masked/non-masked exp
        LXI   H,:C462   Addr FPT (1)
        CNZ   :EA72     Add 1 to Y if X negative
        LXI   H,:E837   Addr FPT (0.25)
        PUSH  H         Save pntr
        CALL  :EA6D     MACC = MACC - 0.25
        CALL  :E9EE     Take abs. value
        LXI   H,:E83B   Addr FPT (0.5)
        CALL  :EA6D     MACC = MACC - 0.5
        CALL  :E9EE     Take abs. value
        POP   H         Get addr FPT (0.25)
        CALL  :EA6D     MACC = MACC - 0.25
L1E134  LXI   H,:00E3
        PUSH  H
        CALL  :E9D6     Copy MACC into 00E3-E6
        XTHL            HL=00E3; stack: 00E7
        CALL  :EA59     MACC = 2 * MACC
        POP   H         HL=00E7
        CALL  :E9DB     Copy 2*MACC into 00E7-EA
        CALL  :EA16     Clear MACC + reg ABCD
        LXI   H,:E83F   Addr Taylor sum constants
        CALL  :E5AA     Calc Taylor sum
        JMP   :C14D     Popall, ret
 REM
* CONSTANTS FOR 'XSIN' AND 'XCOS':
 REM
FPHPI   DATA  :01       FPT (PI/2)
        DATA  :C9
        DATA  :0F
        DATA  :DB
*
L1E304  DATA  :7F       FPT (0.25)
        DATA  :80
        DATA  :00
        DATA  :00
*
L1E305  DATA  :00       FPT (0.5)
        DATA  :80
        DATA  :00
        DATA  :00
*
L1E306  DATA  :03       a1: about PI*2
        DATA  :C9       6.2831853
        DATA  :0F
        DATA  :DB
*
        DATA  :86       a2: about -(PI*2)^3/3!
        DATA  :A5       -41.341681
        DATA  :5D
        DATA  :E2
*
        DATA  :07       a3: about (PI*2)^5/5!
        DATA  :A3       81.602481
        DATA  :34
        DATA  :78
*
        DATA  :87       a4: about -(PI*2)^7/7!
        DATA  :99       -76.581285
        DATA  :29
        DATA  :9E
*
        DATA  :06       a5: about (PI*2)^9/9!
        DATA  :9F       39.760722
        DATA  :0A
        DATA  :FB
*
        DATA  :00       End of table
        DATA  :00
*
*********
* POWER *
*********
*
* MACC = MACC ^ MEM.
*
* Entry: HL points to power in memory.
* Exit:  All registers preserved.
*
* Conditions for a^X:
*       a > 0.
*       ABS (x*ln(a)) in valid range.
*
* Method: a^X = e^(X*ln(a)).
*
XPWR    PUSH  PSW
        PUSH  B
        PUSH  D
        PUSH  H
        PUSH  H         Save addr X
        CALL  :E9F8     Get a in reg ABCD
        POP   H         Restore addr X
        JZ    :E86D     Abort if a = 0
        JM    :E9D0     Argument error if nr < 0
        CALL  :E745     MACC = ln(a)
        CALL  :EA59     MACC = X*ln(a)
        CALL  :E667     MACC = e^(X*ln(a))
XPW10   JMP   :C14D     Popall, ret
*
********
* LOGT *
********
*
* MACC = LOG (MACC).
*
* Method: log(X) = ln(x) / ln(10).
*
* Exit: All registers preserved.
*
XLOG    PUSH  PSW
        PUSH  B
        PUSH  D
        PUSH  H
        CALL  :E745     MACC = ln(ABS(X))
        LXI   H,:E890   Addr 1/ln(10)
        CALL  :EA59     MACC = ln(x)/ln(10)
        JMP   :C14D     Popall, ret
*
********
* ALOG *
********
*
* MACC = ALOG (MACC).
*
* Method: 10^X = e^(X*ln(10)).
*
* Exit: All registers preserved.
*
XALOG   PUSH  PSW
        PUSH  B
        PUSH  D
        PUSH  H
        LXI   H,:E890   Addr 1/ln(10)
        CALL  :EA20     MACC = X*ln(10)
        CALL  :E667     MACC = e^(X*ln(10))
        JMP   :C14D     Popall, ret
 REM
* CONSTANT FOR 'XLOG' AND 'XALOG':
 REM
FLGTI   DATA  :7F       1/ln(10)
        DATA  :DE
        DATA  :5B
        DATA  :D9
*
*******
* TAN *
*******
*
* MACC = TAN (MACC)  (Angle in radians).
*
* Method: tan(X) = sin(X)/cos(X).
*         In-accurate for X close to 0 or close
*         to n*PI/2.
*
* Exit: All registers preserved.
*
XTAN    PUSH  H
        CALL  :C21E     Save X on stack
        CALL  :E7D9     MACC = cos(X)
        LXI   H,:00EF
        CALL  :E11C     Store cos(X) in 00EF-F2
        CALL  :C234     Get X from stack
        CALL  :E7D2     MACC = sin(X)
        CALL  :E108     MACC = sin(X)/cos(X)
        POP   H
        RET
*
********
* ATAN *
********
*
* MACC = ATAN (MACC)  (Angle expressed in radians).
*
* Method: Polynomial approximation.
*
* ATAN(Z) for -0.25 <= Z <= 0.25 approximated by:
*       F(X) = X*(1 - Q1*X^2 + Q2*X^4 - Q3*X^6).
*
* To cope with range:
*       ATAN(-Z) = - ATAN(Z).
*       ATAN(Z) = a(k) + ATAN((Z-b(k))/(Z*b(k)+1)),
*                 with k = 1, 2 or 3,
*                 a(k) = k*PI/7,
*                 b(k) = TAN(a(k))
*
* Values for k:
*       k=0 if ABS(Z) < 0.25
*       k=1 if 0.25 < ABS(Z) < 0.75
*       k=2 if 0.75 < ABS(Z) < 2
*       k=3 if ABS(Z) > 2.
*
* Then X = (Z-b(k))/(Z*b(k)+1), and
*      ATAN(Z) =  a(k) + F(X), if Z >= 0
*      ATAN(Z) = -a(k) - F(X), if Z < 0.
*
XATAN   PUSH  PSW
        PUSH  B
        PUSH  D
        PUSH  H
        CALL  :EBF1     Check if Z=0
        JZ    :E943     Then abort
        PUSH  PSW       Save exp byte
        CALL  :E9EE     reg ABCD = ABS(Z)
        LXI   H,:00EF
        CALL  :E9DB     Copy ABS(Z) into 00EF-F2
 REM
* Calculate k:
 REM
        CPI   :40
        JC    :E8D3     Jump if exp < #40
        CPI   :7F
        MVI   A,:01
        JZ    :E8E6     k=1 if exp=#7F
        LXI   H,:C45E   Addr FPT(0)
        PUSH  H
        JMP   :E915     Cont with k=1, a(k)=0
L1E141  CPI   :01
        MVI   A,:02
        JZ    :E8E6     k=2 if exp=1
        JNC   :E8E3     k=3 if exp >1
        MOV   A,B       Get hibyte mantissa
        RLC
        RLC
        MVI   A,:01     k=1 if (B)= 10...
 REM k=2 if (B)= 11...
        CMC
L1E142  CMC
        ACI   :00
*
L1E143  ADD   A         Final k in A
        ADD   A
        ADD   A         *8
        LXI   H,:E93E   Startaddr for a,b table
        MOV   E,A       )
        MVI   D,:00     ) offset in DE
        DAD   D
        PUSH  H         Addr a(k)
        LXI   D,:0004
        DAD   D
        PUSH  H         Addr b(k)
        CALL  :EA59     MACC = Z*b(k)
        LXI   H,:C462   Addr FPT(1)
        CALL  :EA72     MACC = Z*b(k)+1
        LXI   H,:00DF
        CALL  :E9DB     (Z*b(k)+1) into 00DF-E2
        LXI   H,:00EF
        CALL  :E9FB     ABS(Z) in MACC
        POP   H         Addr b(k)
        CALL  :EA6D     MACC = Z-b(k)
        LXI   H,:00DF
        CALL  :EA20     MACC = X =
 REM = (Z-b(k))/(Z*b(k)+1)
L1E144  LXI   H,:00EF
        PUSH  H
        PUSH  H
        CALL  :E9D6     Copy X into 00EF-F2
        POP   H
        CALL  :EA59     MACC = X^2
        LXI   H,:00E3
        CALL  :E9DB     Copy X^2 into 00E3-E6
        CALL  :E9DB     Copy X^2 into 00E7-EA
        LXI   H,:C462   Addr FPT(1)
        CALL  :E9FB     Copy FPT(1) into MACC
        LXI   H,:E95E   Start table Taylor constants
        CALL  :E5AA     Calc Taylor sum
        POP   H
        CALL  :EA59     Taylor sum * X (=F(X))
        POP   H
        CALL  :EA72     Add a(k) (= ATAN(Z))
        POP   PSW       Get orig. exp byte
        ORA   A         Was Z negative ?
        CM    :E9E4     Then MACC = - ATAN(Z)
L1E145  JMP   :C14D     Popall, ret
 REM
* CONSTANTS FOR 'XATN':
 REM
FATC1   DATA  :7F       a(1): PI/7
        DATA  :E5       0.4487989506
        DATA  :C8
        DATA  :FA
*
        DATA  :7F       b(1): TAN(a(1))
        DATA  :F6       0.4815746188
        DATA  :90
        DATA  :F3
*
        DATA  :00       a(2): 2*PI/7
        DATA  :E5       0.8975979011
        DATA  :C8
        DATA  :FA
*
        DATA  :01       b(2): TAN(a(1))
        DATA  :A0       1.253960337
        DATA  :81
        DATA  :C6
*
        DATA  :01       a(3): 3*PI/7
        DATA  :AC       1.346396852
        DATA  :56
        DATA  :BB
*
        DATA  :03       b(3): TAN(a(3))
        DATA  :8C       4.381286272
        DATA  :33
        DATA  :7F
*
FATPL   DATA  :FF       Q1: about -1/3
        DATA  :AA       -0.333329573
        DATA  :AA
        DATA  :2D
*
        DATA  :7E       Q2: about 1/5
        DATA  :CC       0.199641035
        DATA  :6E
        DATA  :B3
*
        DATA  :FE       Q3: about -1/7
        DATA  :86       -0.131779888
        DATA  :F1
        DATA  :4F
*
        DATA  :00       End of table
        DATA  :00
*
********
* ASIN *
********
*
* MACC = ASIN (MACC).  Result in radians.
*
* Range: -PI/2 < X < PI/2.
*
* Method: ASIN(X) = ATAN(X/SQR(1-x^2)).
*
* Exit: All registers preserved.
*
XASIN   PUSH  PSW
        PUSH  B
        PUSH  D
        PUSH  H
        CALL  :E9F8     Get X in reg ABCD
        MOV   E,A       Exp byte in E
        ANI   :7F       Mask sign
        CPI   :01
        JC    :E999     Jump if in range
        JNZ   :E994     If >2 or <1
        MOV   A,B       )
        ANI   :7F       ) Check if mantissa
        ORA   C         ) = 80 00 00 (= +/- 1)
        ORA   D         )
        JNZ   :E9D0     Error if not
        MOV   A,E       Get exp
        ORA   A         Set flags on it
        LXI   H,:E833   Addr PI/2
        CALL  :E112     Copy PI/2 into MACC
        CM    :E9E4     If nr <0: MACC = -PI/2
FASRET  JMP   :C14D     Popall, ret
*
FAS10   CPI   :40
        JC    :E9D0     Error if exp <#40
FAS20   CALL  :C21E     Save X on stack
        LXI   H,:0000
        DAD   SP        HL=SP
        CALL  :EA59     MACC = X^2
        CALL  :E9E4     MACC = -X^2
        LXI   H,:C462   Addr FPT(1)
        CALL  :EA72     MACC = 1-X^2
        CALL  :E5F8     MACC = SQR(1-X^2)
        LXI   H,:00EF
        CALL  :E11C     SQR(1-X^2) in 00EF-F2
        CALL  :C234     Get X from stack in MACC
        CALL  :E108     MACC = X/(SQR(1-X^2))
        CALL  :E8AC     MACC = ATAN (MACC)
        JMP   :E991     Ready
*
*
********
* ACOS *
********
*
* MACC = ACOS (MACC). Result in radians.
*
* Range: 0 < X < PI.
*
* Method: ACOS(X) = PI/2 - ASIN(X).
*
* Exit: All registers preserved.
*
XACOS   CALL  :E96C     MACC = ASIN(X)
        CALL  :E14A     MACC = -ASIN(X)
        PUSH  H
        LXI   H,:E833   Addr PI/2
        CALL  :EDAA     MACC = PI/2-ASIN(X)
        POP   H
        RET
 REM
* Error exit:
 REM
FASER   CALL  :C05E     Run argument error
        JMP   :E991     Abort
*
*******************************************
* COPY MACC INTO OPERAND AND INTO A,B,C,D *
*******************************************
*
* Entry: HL points to operand.
* Exit:  HL points past operand.
*        AFBCD set as for ATEST.
*
* From ASTORE used to store reg A,B,C,D into
* an operand, pointed at by HL.
*
ASAVE   PUSH  H
        CALL  :E9F8     Copy MEM into MACC and ABCD
        POP   H
ASTORE  MOV   M,A       )
        INX   H         )
        MOV   M,B       ) Copy reg A,B,C,D into MEM
        INX   H         )
        MOV   M,C       )
        INX   H         )
        MOV   M,D       )
        INX   H         
        RET
*
*******************************
* SUBROUTINE CHANGE SIGN MACC *
*******************************
*
ACHGS   CALL  :EBF1     Check if MACC empty
        RZ              Then ready
        LXI   B,:FF80   Set mask
        JMP   :E9F1     Change sign bit
*
*****************************
* SUBROUTINE FPT ABS (MACC) *
*****************************
*
* From ATEST also used to copy MACC into ABCD.
* From L1E158 used to copy operand (pointed at
* by HL) into ABCD and into MACC.
*
L1E155  LXI   B,:7F00   Set mask
L1E156  LXI   H,:00D5   Addr MACC
        MOV   A,B       Mask in A
        ANA   M         AND exp byte with mask
        XRA   C         Set sign bit = 0
        MOV   M,A       Update exp byte MACC
*
ATEST   LXI   H,:00D5   Addr MACC
L1E158  CALL  :EBF4     Check if MEM = 0, get
 REM exp byte in A
        JZ    :EA16     Then clear MACC + ABCD
        MOV   E,A       exp byte in E
        INX   H         )
        MOV   B,M       )
        INX   H         ) Mantissa from MEM
        MOV   C,M       ) into BCD
        INX   H         )
        MOV   D,M       )
        LXI   H,:00D5   Addr MACC
        JMP   :EB17     Copy ABCD into MACC;
 REM exp from E in A, flags
 REM set on exp ORI 01
*
*
*
        END
